#include "stdafx.h"

#include <MyFC/StringContainer.h>
#include <MyFC/Utility.h>
#include <algorithm>
#include <boost/bind.hpp>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

namespace My {

StringContainer::StringContainer()
{
	m_Alignment = ALIGN_HLEFT|ALIGN_VCENTER;
	m_Gap = 10;
	m_BorderX = 4;
	m_BorderY = 2;
}

bool StringContainer::AreAllChildrenProvided() const
{
	return std::find(m_Children.begin(), m_Children.end(), (Widget *)0) 
		== m_Children.end();
}

void StringContainer::SetSize(Size s) 
{
	bool Removed = false;
	for (Size n = s; n < m_Children.size(); ++n) {
		if (m_Children[n]) {
			Remove(m_Children[n]);
			Removed = true;
		}
	}
	m_Children.resize(s);
	if (Removed)
		LayoutControls();
}

void StringContainer::SetChild(Size n, Widget * pWidget) 
{
	if (pWidget != m_Children[n]) {
		if (m_Children[n] != 0)
			Remove(m_Children[n]);
		m_Children[n] = pWidget;
		if (m_Children[n] != 0)
			Add(m_Children[n]);
		LayoutControls();
	}
}

void StringContainer::AppendChild(Widget * pWidget)
{
	m_Children.push_back(pWidget);
	Add(pWidget);
	LayoutControls();
}

void StringContainer::SetAlignment(int a)
{
	if (a != m_Alignment) {
		m_Alignment = a;
		LayoutControls();
	}
}

void StringContainer::SetGap(int g)
{
	if (g != m_Gap) {
		m_Gap = g;
		LayoutControls();
	}
}

void StringContainer::SetBorderX(int b)
{
	if (b != m_BorderX) {
		m_BorderX = b;
		LayoutControls();
	}
}

void StringContainer::SetBorderY(int b)
{
	if (b != m_BorderY) {
		m_BorderY = b;
		LayoutControls();
	}
}

void StringContainer::LayoutControls() 
{
	if (!AreAllChildrenProvided())
		return;

	CSize s = GetPreferredSize();
	CRect r(CPoint(0, 0), s);
	CRect rClient = ClientRect();
	r = AlignRect(rClient, r, m_Alignment);

	int left = r.left + m_BorderX;
	std::vector<Widget *>::iterator i;
	for (i = m_Children.begin(); i != m_Children.end(); ++i) {
		Widget * pWidget = *i;
		CRect rWidget(CPoint(left, r.top + m_BorderY), pWidget->GetPreferredSize());
		rWidget = AlignRect(r, rWidget, m_Alignment & ALIGN_VMASK);
		rWidget.IntersectRect(&rWidget, &rClient);
		pWidget->SetBounds(rWidget);
		left = rWidget.right + m_Gap;
	}
}

struct SizeAccumulator : std::unary_function<CSize, void> {
	CSize Total;
	SizeAccumulator() : Total(0, 0) { }
	void operator () (CSize const & s) { 
		Total.cx += s.cx;
		if (Total.cy < s.cy)
			Total.cy = s.cy;
	}
};

CSize StringContainer::GetPreferredSize() const
{
	if (!AreAllChildrenProvided())
		return CSize(0,0);

	SizeAccumulator Accu;

	std::for_each(m_Children.begin(), m_Children.end(), 
		boost::bind(boost::ref(Accu), boost::bind(&Widget::GetPreferredSize, _1)));

	Accu.Total.cx += m_Children.size() * m_Gap + 2 * m_BorderX;
	Accu.Total.cy += 2 * m_BorderY;

	return Accu.Total;
}

void StringContainer::HandleUpdateUI()
{
	LayoutControls();
}

} // My
